/*
 * Animation.h
 *
 *	Author: stravant
 *	Description:
 *		
 */

#ifndef ANIMATION_H_
#define ANIMATION_H_

#include "../core/Rect.h"
#include "../core/Vec.h"
#include "../core/Timer.h"

namespace tbt {

class Animation;

class AnimationDelegate {
public:
	virtual void animationEnded(Animation*) {}
	virtual void animationProgressed(Animation*) {}
	virtual void animationCanceled(Animation*) {}
};

class Animation: private TickerPeriodic {
public:
	Animation();
	Animation(AnimationDelegate*);
	virtual ~Animation();

	void start();
	void stop();

	bool isRunning() {return mRunning; }
	void setDelegate(AnimationDelegate* delegate) {mDelegate = delegate; }

	virtual double getCurrentValue() const = 0;
	template<class T> T getValueBetween(T start, T target) const;
	template<class T> Vec<T> getValueBetween(const Vec<T>& a, const Vec<T>& b) const;

	void setFramerate(int fps);

protected:
	virtual void animationStep(TimeDelta elapsed) = 0;
	virtual void animationStarted() = 0;
	virtual void animationStopped() = 0;
	virtual bool shouldStopSendCancel() {return false; }

	AnimationDelegate* getDelegate() const {return mDelegate; }
	TimeDelta getElapsedTime() const {return mTimer.elapsed(); }

private:
	virtual void periodicTick(Time time);

private:
	bool mRunning;
	AnimationDelegate* mDelegate;
	Timer mTimer;
};

template <class T>
T Animation::getValueBetween(T start, T target) const {
	return start + static_cast<T>(static_cast<double>(target-start)*getCurrentValue());
}

template <class T>
Vec<T> Animation::getValueBetween(const Vec<T>& a, const Vec<T>& b) const {
	return Vec<T>(getValueBetween(a.x(), b.x()), getValueBetween(a.y(), b.y()));
}

//////////////////////////////////////////

class AnimationLinear: public Animation {
public:
	AnimationLinear(AnimationDelegate* delegate);
	~AnimationLinear();

	virtual double getCurrentValue() const {return mCurrent; }
protected:
	void setTween(double from = 0.0, double to = 1.0, double rate = 1.0);

	virtual void animationStep(TimeDelta elapsed);
	virtual void animationStarted();
	virtual void animationStopped();

	virtual void animateLinear(double state) {}
private:
	double mFrom, mTo;
	double mCurrent;
	double mRate;
	TimeDelta mLastElapsed;
};

/////////////////////////////////////////

class AnimationSlide: public AnimationLinear {
public:
	AnimationSlide(TimeDelta duration, AnimationDelegate* delegate);
	~AnimationSlide();

	virtual void slideShow();
	virtual void slideHide();

//private:
//	virtual void animateLinear(double n) {mState = n; }
//	virtual double getCurrentValue() {return mState; }

private:
	enum SlideState {
		kSlideShow,
		kSlideHide,
	};

private:
	SlideState mSlideState;
	TimeDelta mSlideDuration;
	double mSlideRate;
};

}

#endif /* ANIMATION_H_ */























